#include "sys_dma.h"
#include "sys_interrupt.h"
#include "sys_uart.h"
#include "sys_gpio.h"
#include "sys_delay.h"
#include "sys_io.h"
#include "sys_timer.h"
#include "sys_cache.h"
#include "sys_clock.h"

/*DMA-寄存器地址*/
#define DMA_Base_Address (0x01C02000)
#define write_update_bits(addr,bit,Clear,Value)	write32(addr,read32(addr) & (~((u64_t)(Clear)<<bit)) | ((u64_t)(Value)<<bit)    )

#define CCU_Base_Address     	  		(u32_t)0x01C20000
#define CCU_BUS_CLK_GATING_REG0 		(u32_t)CCU_Base_Address+0x0060
#define CCU_BUS_CLK_GATING_REG1 		(u32_t)CCU_Base_Address+0x0064
#define CCU_BUS_CLK_GATING_REG2 		(u32_t)CCU_Base_Address+0x0068
#define CCU_BUS_SOFT_RST_REG0 			(u32_t)CCU_Base_Address+0x02C0
#define CCU_BUS_SOFT_RST_REG1 			(u32_t)CCU_Base_Address+0x02C4
#define CCU_BUS_SOFT_RST_REG2 			(u32_t)CCU_Base_Address+0x02D0
/////////////////////////////////////////////
/*DMA初始化*/
void DMA_Init(void)
{
	Open_Dev_Clock(DMA_CLOCK);
}
/*DMA退出*/
void DMA_Exit(void)
{
	Close_Dev_Clock(DMA_CLOCK);
}
/*dma enable*/
void DMA_Enable(DMA* dma)
{
	S_BIT(dma->addr+0x0,31);
}
/*dma disable*/
void DMA_Disable(DMA* dma)
{
	C_BIT(dma->addr+0x0,31);
}
/*Normal DMA dma_ch Half Transfer Interrupt Pending (n=0~3)*/
int DMA_Get_Half_TIP(DMA* dma)
{
	if(read32(DMA_Base_Address+0x4)&((0x1<<(2*dma->Ch+0))<<(dma->Type==NDMA?0:16)))
	{
		S_BIT(DMA_Base_Address+0x4,((2*dma->Ch+0)<<(dma->Type==NDMA?0:16)));//清中断
		return 1;
	}
	return 0;
}
/*Normal DMA n Full Transfer Interrupt Pending (n=0~3)*/
int DMA_Get_Full_TIP(DMA* dma)
{
	if(read32(DMA_Base_Address+0x4)&((0x1<<(2*dma->Ch+1))<<(dma->Type==NDMA?0:16)))
	{
		S_BIT(DMA_Base_Address+0x4,((2*dma->Ch+1)<<(dma->Type==NDMA?0:16)));//清中断
		return 1;
	}
	return 0;
}
/*中断使能 (n=0~3)*/
int DMA_Interrupt_Control_Half(DMA* dma,int c)
{
	if(dma->Type)//初始化过
	{	
		if(c)S_BIT(DMA_Base_Address+0x0,((2*dma->Ch+0)+((dma->Type==NDMA)?0:16)));
		else C_BIT(DMA_Base_Address+0x0,((2*dma->Ch+0)+((dma->Type==NDMA)?0:16)));
	}else
	{
		sysprintf("Init err...\r\n");
		return -1;
	}	
	return 0;
}
/*中断使能 (n=0~3)*/
int DMA_Interrupt_Control_Full(DMA* dma,int c)
{
	if(dma->Type)//初始化过
	{
		if(c)S_BIT(DMA_Base_Address+0x0,((2*dma->Ch+1)+((dma->Type==NDMA)?0:16)));
		else C_BIT(DMA_Base_Address+0x0,((2*dma->Ch+1)+((dma->Type==NDMA)?0:16)));
	}else
	{
		sysprintf("Init err...\r\n");
		return -1;
	}
	return 0;
}
/*
NDMA_Config
*/
int DMA_Config(DMA* dma)
{
	if(dma->Byte_Counter>(dma->Type==NDMA ? (dma->Read_Byte_Counter_Enable ? 131072 : 262144) : 16777216)) 
	{
		sysprintf("ERR:Byte_Counter ERR \r\n");
		return -1;
	}	
	//返回地址
	dma->addr=(DMA_Base_Address+dma->Type+dma->Ch*0x20);
	//
	if(dma->Continuous_Mode_Enable==1)S_BIT(DMA_Base_Address+0x8,16);//连续模式下要设置为1
	else C_BIT(DMA_Base_Address+0x8,16);//设置为0
	write32(dma->addr+0xC,dma->Byte_Counter);//设置BCNT
	
	write_update_bits(dma->addr+0x0,29,0x1,dma->Continuous_Mode_Enable);//设置DMA连续使能
	write_update_bits(dma->addr+0x0,15,0x1,dma->Read_Byte_Counter_Enable);//读计数值使能
  //设置源
	write32(dma->addr+0x4,(u32_t)dma->Source_Address);//设置源地址
	write_update_bits(dma->addr+0x0,0,0x1F,dma->Source_DRQ_Type);//设置源类型
	write_update_bits(dma->addr+0x0,8,0x3,dma->Source_Data_Width);//设置源宽度为16位
	write_update_bits(dma->addr+0x0,5,0x3,dma->Source_Address_Type);//设置源地址模式
	write_update_bits(dma->addr+0x0,7,0x1,dma->Source_Burst_Length);//源 Burst Length
  //设置目标
	write32(dma->addr+0x8,(u32_t)dma->Destination_Address);//设置目标地址
	write_update_bits(dma->addr+0x0,16,0x1F,dma->Destination_DRQ_Type);//设置目标类型
	write_update_bits(dma->addr+0x0,24,0x3,dma->Destination_Data_Width);//设置目标宽度为16位
	write_update_bits(dma->addr+0x0,21,0x3,dma->Destination_Address_Type);//设置目标地址模式
	write_update_bits(dma->addr+0x0,23,0x1,dma->Destination_Burst_Length);//目标 Burst Length
	
	return 0;
}


